Отправка письма с вложением. Часть 2
Сегодняшний пост - по просьбам трудящихся. На форуме мне задали вопрос, как отправить по почте письмо с несколькими вложенными файлами. Поскольку такая заметка на блоге уже есть, то сегодня - продолжение. Форма для отправки письма с тремя вложенными файлами выглядит так:
Количество файлов, которые прикрепляются к письму не ограничено. Просто добавляем в форму столько полей для загрузки файлов, сколько нужно:
Файл: <input type="file" name="file[]" />
Файл: <input type="file" name="file[]" />
Файл: <input type="file" name="file[]" />
Файл: <input type="file" name="file[]" />
Файл: <input type="file" name="file[]" />
Ну и собственно сам скрипт:
<?php
session_start();
$admin = 'admin@mail.ru';
if ( isset( $_POST['sendMail'] ) ) {
$name = substr( $_POST['name'], 0, 64 );
$email = substr( $_POST['email'], 0, 64 );
$subject = substr( $_POST['subject'], 0, 64 );
$message = substr( $_POST['message'], 0, 250 );
$error = '';
if ( empty( $name ) ) $error = $error.'<li>Не заполнено поле "Имя"</li>';
if ( empty( $email ) ) $error = $error.'<li>Не заполнено поле "E-mail"</li>';
if ( empty( $subject ) ) $error = $error.'<li>Не заполнено поле "Тема"</li>';
if ( empty( $message ) ) $error = $error.'<li>Не заполнено поле "Сообщение"</li>';
if ( !empty( $email ) and !preg_match( "#^[0-9a-z_\-\.]+@[0-9a-z\-\.]+\.[a-z]{2,6}$#i", $email ) )
$error = $error.'<li>поле "E-mail" должно соответствовать формату somebody@somewhere.ru</li>';
if ( !empty( $error ) ) {
$_SESSION['sendMailForm']['error'] = '<p>При заполнении формы были допущены ошибки:</p><ul>'.$error.'</ul>';
$_SESSION['sendMailForm']['name'] = $name;
$_SESSION['sendMailForm']['email'] = $email;
$_SESSION['sendMailForm']['subject'] = $subject;
$_SESSION['sendMailForm']['message'] = $message;
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$filepath = array();
$filename = array();
for( $i = 0; $i < count($_FILES['file']); $i++) {
if ( !empty( $_FILES['file']['tmp_name'][$i] ) and $_FILES['file']['error'][$i] == 0 ) {
$filepath[] = $_FILES['file']['tmp_name'][$i];
$filename[] = $_FILES['file']['name'][$i];
}
}
$body = "АВТОР:\r\n".$name."\r\n\r\n";
$body .= "E-MAIL:\r\n".$email."\r\n\r\n";
$body .= "ТЕМА:\r\n".$subject."\r\n\r\n";
$body .= "СООБЩЕНИЕ:\r\n".$message;
if ( send_mail($admin, $body, $email, $filepath, $filename) )
$_SESSION['success'] = true;
else
$_SESSION['success'] = false;
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Вспомогательная функция для отправки почтового сообщения с вложением
function send_mail($admin, $body, $email, $filepath, $filename)
{
$subject = '=?windows-1251?B?'.base64_encode('Заполнена форма на сайте').'?=';
$boundary = "--".md5(uniqid(time())); // генерируем разделитель
$headers = "From: ".strtoupper($_SERVER['SERVER_NAME'])." <".$email.">\r\n";
$headers .= "Return-path: <".$email.">\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .="Content-Type: multipart/mixed; boundary=\"".$boundary."\"\r\n";
$multipart = "--".$boundary."\r\n";
$multipart .= "Content-type: text/plain; charset=\"windows-1251\"\r\n";
$multipart .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
$body = quoted_printable_encode( $body )."\r\n\r\n";
$multipart .= $body;
$file = '';
$count = count( $filepath );
if ( $count > 0 ) {
for ( $i = 0; $i < $count; $i++ ) {
$fp = fopen($filepath[$i], "r");
if ( $fp ) {
$content = fread($fp, filesize($filepath[$i]));
fclose($fp);
$file .= "--".$boundary."\r\n";
$file .= "Content-Type: application/octet-stream\r\n";
$file .= "Content-Transfer-Encoding: base64\r\n";
$file .= "Content-Disposition: attachment; filename=\"".$filename[$i]."\"\r\n\r\n";
$file .= chunk_split(base64_encode($content))."\r\n";
}
}
}
$multipart .= $file."--".$boundary."--\r\n";
if( mail($admin, $subject, $multipart, $headers) )
return true;
else
return false;
}
function quoted_printable_encode ( $string ) {
// rule #2, #3 (leaves space and tab characters in tact)
$string = preg_replace_callback (
'/[^\x21-\x3C\x3E-\x7E\x09\x20]/',
'quoted_printable_encode_character',
$string
);
$newline = "=\r\n"; // '=' + CRLF (rule #4)
// make sure the splitting of lines does not interfere with escaped characters
// (chunk_split fails here)
$string = preg_replace ( '/(.{73}[^=]{0,3})/', '$1'.$newline, $string);
return $string;
}
function quoted_printable_encode_character ( $matches ) {
$character = $matches[0];
return sprintf ( '=%02x', ord ( $character ) );
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Отправить письмо</title>
</head>
<body>
<?php
if ( isset( $_SESSION['sendMailForm'] ) ) {
echo $_SESSION['sendMailForm']['error'];
$name = htmlspecialchars ( $_SESSION['sendMailForm']['name'] );
$email = htmlspecialchars ( $_SESSION['sendMailForm']['email'] );
$subject = htmlspecialchars ( $_SESSION['sendMailForm']['subject'] );
$message = htmlspecialchars ( $_SESSION['sendMailForm']['message'] );
unset( $_SESSION['sendMailForm'] );
} else {
$name = '';
$email = '';
$subject = '';
$message = '';
}
if ( isset( $_SESSION['success'] ) ) {
if ( $_SESSION['success'] )
echo '<p>Письмо успешно отправлено</p>';
else
echo '<p>Ошибка при отправке письма</p>';
unset( $_SESSION['success'] );
}
?>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST" enctype="multipart/form-data">
<table>
<tr><td>Имя:</td><td><input type="text" name="name" maxlength="64" value="<?php echo $name ?>" /></td></tr>
<tr><td>E-mail:</td><td><input type="text" name="email" maxlength="64" value="<?php echo $email ?>" /></td></tr>
<tr><td>Тема:</td><td><input type="text" name="subject" maxlength="64" value="<?php echo $subject ?>" /></td></tr>
<tr><td>Сообщение:</td><td><textarea name="message" rows="5" cols="30"><?php echo $message ?></textarea></td></tr>
<tr><td>Файл:</td><td><input type="file" name="file[]" /></td></tr>
<tr><td>Файл:</td><td><input type="file" name="file[]" /></td></tr>
<tr><td>Файл:</td><td><input type="file" name="file[]" /></td></tr>
<tr><td> </td><td><input type="submit" name="sendMail" value="Отправить" /></td></tr>
</table>
</form>
</body>
</html>
session_start();
$admin = 'admin@mail.ru';
if ( isset( $_POST['sendMail'] ) ) {
$name = substr( $_POST['name'], 0, 64 );
$email = substr( $_POST['email'], 0, 64 );
$subject = substr( $_POST['subject'], 0, 64 );
$message = substr( $_POST['message'], 0, 250 );
$error = '';
if ( empty( $name ) ) $error = $error.'<li>Не заполнено поле "Имя"</li>';
if ( empty( $email ) ) $error = $error.'<li>Не заполнено поле "E-mail"</li>';
if ( empty( $subject ) ) $error = $error.'<li>Не заполнено поле "Тема"</li>';
if ( empty( $message ) ) $error = $error.'<li>Не заполнено поле "Сообщение"</li>';
if ( !empty( $email ) and !preg_match( "#^[0-9a-z_\-\.]+@[0-9a-z\-\.]+\.[a-z]{2,6}$#i", $email ) )
$error = $error.'<li>поле "E-mail" должно соответствовать формату somebody@somewhere.ru</li>';
if ( !empty( $error ) ) {
$_SESSION['sendMailForm']['error'] = '<p>При заполнении формы были допущены ошибки:</p><ul>'.$error.'</ul>';
$_SESSION['sendMailForm']['name'] = $name;
$_SESSION['sendMailForm']['email'] = $email;
$_SESSION['sendMailForm']['subject'] = $subject;
$_SESSION['sendMailForm']['message'] = $message;
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$filepath = array();
$filename = array();
for( $i = 0; $i < count($_FILES['file']); $i++) {
if ( !empty( $_FILES['file']['tmp_name'][$i] ) and $_FILES['file']['error'][$i] == 0 ) {
$filepath[] = $_FILES['file']['tmp_name'][$i];
$filename[] = $_FILES['file']['name'][$i];
}
}
$body = "АВТОР:\r\n".$name."\r\n\r\n";
$body .= "E-MAIL:\r\n".$email."\r\n\r\n";
$body .= "ТЕМА:\r\n".$subject."\r\n\r\n";
$body .= "СООБЩЕНИЕ:\r\n".$message;
if ( send_mail($admin, $body, $email, $filepath, $filename) )
$_SESSION['success'] = true;
else
$_SESSION['success'] = false;
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Вспомогательная функция для отправки почтового сообщения с вложением
function send_mail($admin, $body, $email, $filepath, $filename)
{
$subject = '=?windows-1251?B?'.base64_encode('Заполнена форма на сайте').'?=';
$boundary = "--".md5(uniqid(time())); // генерируем разделитель
$headers = "From: ".strtoupper($_SERVER['SERVER_NAME'])." <".$email.">\r\n";
$headers .= "Return-path: <".$email.">\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .="Content-Type: multipart/mixed; boundary=\"".$boundary."\"\r\n";
$multipart = "--".$boundary."\r\n";
$multipart .= "Content-type: text/plain; charset=\"windows-1251\"\r\n";
$multipart .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
$body = quoted_printable_encode( $body )."\r\n\r\n";
$multipart .= $body;
$file = '';
$count = count( $filepath );
if ( $count > 0 ) {
for ( $i = 0; $i < $count; $i++ ) {
$fp = fopen($filepath[$i], "r");
if ( $fp ) {
$content = fread($fp, filesize($filepath[$i]));
fclose($fp);
$file .= "--".$boundary."\r\n";
$file .= "Content-Type: application/octet-stream\r\n";
$file .= "Content-Transfer-Encoding: base64\r\n";
$file .= "Content-Disposition: attachment; filename=\"".$filename[$i]."\"\r\n\r\n";
$file .= chunk_split(base64_encode($content))."\r\n";
}
}
}
$multipart .= $file."--".$boundary."--\r\n";
if( mail($admin, $subject, $multipart, $headers) )
return true;
else
return false;
}
function quoted_printable_encode ( $string ) {
// rule #2, #3 (leaves space and tab characters in tact)
$string = preg_replace_callback (
'/[^\x21-\x3C\x3E-\x7E\x09\x20]/',
'quoted_printable_encode_character',
$string
);
$newline = "=\r\n"; // '=' + CRLF (rule #4)
// make sure the splitting of lines does not interfere with escaped characters
// (chunk_split fails here)
$string = preg_replace ( '/(.{73}[^=]{0,3})/', '$1'.$newline, $string);
return $string;
}
function quoted_printable_encode_character ( $matches ) {
$character = $matches[0];
return sprintf ( '=%02x', ord ( $character ) );
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Отправить письмо</title>
</head>
<body>
<?php
if ( isset( $_SESSION['sendMailForm'] ) ) {
echo $_SESSION['sendMailForm']['error'];
$name = htmlspecialchars ( $_SESSION['sendMailForm']['name'] );
$email = htmlspecialchars ( $_SESSION['sendMailForm']['email'] );
$subject = htmlspecialchars ( $_SESSION['sendMailForm']['subject'] );
$message = htmlspecialchars ( $_SESSION['sendMailForm']['message'] );
unset( $_SESSION['sendMailForm'] );
} else {
$name = '';
$email = '';
$subject = '';
$message = '';
}
if ( isset( $_SESSION['success'] ) ) {
if ( $_SESSION['success'] )
echo '<p>Письмо успешно отправлено</p>';
else
echo '<p>Ошибка при отправке письма</p>';
unset( $_SESSION['success'] );
}
?>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST" enctype="multipart/form-data">
<table>
<tr><td>Имя:</td><td><input type="text" name="name" maxlength="64" value="<?php echo $name ?>" /></td></tr>
<tr><td>E-mail:</td><td><input type="text" name="email" maxlength="64" value="<?php echo $email ?>" /></td></tr>
<tr><td>Тема:</td><td><input type="text" name="subject" maxlength="64" value="<?php echo $subject ?>" /></td></tr>
<tr><td>Сообщение:</td><td><textarea name="message" rows="5" cols="30"><?php echo $message ?></textarea></td></tr>
<tr><td>Файл:</td><td><input type="file" name="file[]" /></td></tr>
<tr><td>Файл:</td><td><input type="file" name="file[]" /></td></tr>
<tr><td>Файл:</td><td><input type="file" name="file[]" /></td></tr>
<tr><td> </td><td><input type="submit" name="sendMail" value="Отправить" /></td></tr>
</table>
</form>
</body>
</html>
Ссылки по теме:
povor:
Очень помогла Ваша форма, всё же немного пришлось её переделать. Теперь всё работает как надо
3 Ноябрь 2008, 17:39Roma:
а как к этой форме добавить капчу?
10 Ноябрь 2008, 15:29admin:
Roma:
10 Ноябрь 2008, 23:13Защитное изображение для HTML-формы
demarcruise:
Понять немогу, у меня тоже неработает отправка ыложений, пробовал на двух хостингах, на одном работает нормально, а на другом (мастерхост) недоходят вложения… подскажите как быть?
6 Февраль 2009, 22:39Mihail:
Большое спасибо! все работает просто отлично!
3 Ноябрь 2009, 20:44Автор красавчик=0
Сергей:
Спасибо большое за скрипт, именно то что я искал, с вложениями и с защитой полей ввода. Сначала поставил первый скрипт, и он у меня не сработал, потом взял этот и поменял расширения файла на .php и он заработал. Сейчас несколько его переделал. И теперь у меня две версии, так что можно сам скрипт выносить в отдельный файл.
В общем большое спасибо автору! И надеюсь на этом сайте найду ещё много полезного.
2 Декабрь 2009, 10:23Светлана:
Скрипт отлично работает, по крайней мере на средних файлах. Пробовала отправку 1,5Мб вместе с мелким, письмо дошло. Боялась, что время работы скрипта не позволит даже загрузить его на сервер, но все получилось.
8 Декабрь 2009, 21:33Спасибо Вам огромное!
Александр:
классный скрипт, рабочий !!! его и искал
9 Январь 2010, 23:10Наталья:
Скрипт очень помог, раньше пробовала сама, но все как-то коряво получалось, а тут как будто мозаика сложилась - все на своих местах - и проверка полей ввода, и обработка нескольких файлов, а не одного.
9 Июнь 2010, 15:11Хотелось бы попросить автора рассказать как можно изменить скрипт с тем, чтобы данные заносились в БД. Пост о хранении изображений в базе данных MySQL читала, все вроде понятно, но до кучи никак не могу сложить.
Андрей:
Скажите пожалуйста, а как можно пользователю отказаться от отправления прикрепленного файла, если он уже выбрал файл. Как можно удалить файл из сообщения, если он уже выбран.
13 Июль 2011, 16:27Дмитрий:
Только первые 5 ячеек для вложения работают.
То-есть, если сделать десять ячеек и вложить во все 10, прийдут первых 5 вложений, если вложить только в последние пять не прийдёт ничего. Если вложить, допустим в 2, 4, 6, 9 - прийдут файлы из 2-й и 4-й. Значит ограничение не на количество вложений до 5, а именно на то, что работают только первые 5 ячеек, даже один файл вложенный после 5-й ячейки не доходит, а до 5-й доходят хоть 1 хоть 5 файлов.
Чем это объяснить?
1 Июль 2012, 15:29